package com.yuyou.fn.tradingservice.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.github.wens.mybatisplus.toolkit.IdWorker;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.CriteriaUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.service.IRoomTimeService;
import com.yuyou.fn.platform.entity.SysUser;
import com.yuyou.fn.settlement.entity.MainAccount;
import com.yuyou.fn.settlement.service.IMainAccountService;
import com.yuyou.fn.settlement.service.ISettlementService;
import com.yuyou.fn.tradingservice.entity.*;
import com.yuyou.fn.tradingservice.mapper.ServiceOrderMapper;
import com.yuyou.fn.tradingservice.service.*;
import com.yuyou.fn.tradingservice.vo.ServiceOrderItemVo;
import com.yuyou.fn.tradingservice.vo.ServiceOrderVo;
import com.yuyou.fn.tradingservice.vo.ServiceProductOrderVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * ServiceOrder 表数据服务层接口实现类
 */
@Service
public class ServiceOrderServiceImpl extends SuperServiceImpl<ServiceOrderMapper, ServiceOrder, Long> implements IServiceOrderService {

    @Resource
    private IServiceOrderItemService orderItemService;

    @Resource
    private IShippingAddressService shippingAddressService;


    @Resource
    private IRoomTimeService roomTimeService;

    @Resource
    private IServiceProductService serviceProductService;

    @Resource
    private IServiceOrderItemService serviceOrderItemService;

    @Resource
    private IServiceProductListingService serviceProductListingService;

    @Resource
    private IMainAccountService mainAccountService;

    @Resource
    private IServiceMerchantService serviceMerchantService;

    @Resource
    private IPersonLeaseMessageService personLeaseMessageService;

    @Resource
    private IServiceCategoryService serviceCategoryService;

    @Resource
    private ISettlementService settlementService;


    @Override
    @Transactional
    public void payServiceOrder(Long orderId, BigDecimal paidAmount,Integer payWay) {
        ServiceOrder serviceOrder=this.findById(orderId);
        if (serviceOrder!=null){
            if (serviceOrder.getChargingStatus()==2){
                if (payWay==3){
                    throw new BusException("orderId为:"+orderId+"的订单已经支付");
                }else {
                    return;
                }
            }

            BigDecimal temp=serviceOrder.getPayableAmount().subtract(serviceOrder.getPaidAmount());

            if (temp.doubleValue()>paidAmount.doubleValue()){
                throw new BusException("付款金额小于应付金额");
            }

            List<ServiceOrderItem> serviceOrderItemList=serviceOrderItemService.findByOrderIdAndChargingStatus(serviceOrder.getOrderId(),0);
            for (ServiceOrderItem serviceOrderItem:serviceOrderItemList){
                ServiceOrderItem serviceOrderItem1=new ServiceOrderItem();
                serviceOrderItem1.setChargingStatus(2);
                serviceOrderItem1.setOrderStatus(2);
                serviceOrderItem1.setOrderItemId(serviceOrderItem.getOrderItemId());
                serviceOrderItem1.setUpdateTime(TimeUtils.now());
                serviceOrderItem1.setPaidAmount(serviceOrderItem.getPayableAmount());
                serviceOrderItem1.setPayWay(payWay);
                serviceOrderItem1.setPayTime(TimeUtils.now());
                serviceOrderItemService.updateSelectiveById(serviceOrderItem1);
                /*更新商品销量*/
                if (serviceOrderItem.getType()==0){
                    ServiceProduct serviceProduct=serviceProductService.findById(serviceOrderItem.getProductId());
                    if (serviceProduct!=null){
                        Integer amount=serviceOrderItem.getQuantity()+serviceProduct.getAmount();
                        ServiceProduct newServiceProduct=new ServiceProduct();
                        newServiceProduct.setProductId(serviceProduct.getProductId());
                        newServiceProduct.setAmount(amount);
                        newServiceProduct.setUpdateTime(TimeUtils.now());
                        serviceProductService.updateSelectiveById(newServiceProduct);
                    }
                }
                if (payWay==3){
                    ServiceCategory serviceCategory=serviceCategoryService.findById(serviceOrderItem.getCategoryId());
                    String remark=(serviceOrderItem.getType()==2?"租赁":"商品")+"订单("+serviceOrderItem.getProductName()+")购买";
                    if (serviceOrderItem.getType()==2){
                        settlementService.bookLeaseDeal(serviceOrderItem.getPayMainAccountId(),serviceOrderItem.getProfitMainAccountId(),serviceOrderItem.getPayableAmount(),remark,serviceOrderItem.getMinStartDate(),serviceOrderItem.getMaxEndDate(),serviceOrderItem.getOrderItemId());
                    }else if(serviceOrderItem.getType()==0){
                        settlementService.bookProductDeal(serviceOrderItem.getPayMainAccountId(),serviceCategory.getFeeCategoryId(),serviceOrderItem.getProfitMainAccountId(),serviceOrderItem.getPayableAmount(),remark,serviceOrderItem.getOrderItemId());
                    }
                }
            }

            List<String> personLeaseStr=BeanUtils.toList(serviceOrderItemList,"personLeaseIds");
            String str=StringUtils.join(personLeaseStr,",");
            List<Long> personLeaseIds=Utils.toLongIds(str);
            if (personLeaseIds.size()>0){
                personLeaseMessageService.changeLeaseStateByIds(personLeaseIds,1);
            }
            ServiceOrder serviceOrder1=new ServiceOrder();
            serviceOrder1.setChargingStatus(2);
            serviceOrder1.setOrderId(serviceOrder.getOrderId());
            serviceOrder1.setPaidAmount(paidAmount);
            serviceOrder1.setUpdateTime(TimeUtils.now());
            serviceOrder1.setPayWay(payWay);
            this.updateSelectiveById(serviceOrder1);
        }else{
            serviceOrderItemService.payServiceOrderItem(orderId,paidAmount,payWay);
        }

    }

    @Override
    public void changePayableAmount(Long orderId, BigDecimal paidAmount) {
        ServiceOrder serviceOrder=new ServiceOrder();
        serviceOrder.setOrderId(orderId);
        serviceOrder.setPaidAmount(paidAmount);
        updateSelectiveById(serviceOrder);
    }

    @Override
    @Transactional
    public ServiceOrder createOrder(Long addressId, SysUser user, List<Long> listingIds, Long payMainAccountId) {
        List<ServiceProductListing> serviceProductListingList = serviceProductListingService.findByIds(listingIds);
        serviceProductListingService.checkLeaseListing(serviceProductListingList,0);
        ShippingAddress shippingAddress = shippingAddressService.findById(addressId);
        if (listingIds==null || listingIds.size()<=0){
            throw new BusException("缺乏购买信息");
        }

        if (shippingAddress == null) {
            throw new BusException("查不到收货信息,下单失败");
        }

        MainAccount mainAccount = mainAccountService.findById(payMainAccountId);
        if (mainAccount == null) {
            throw new BusException("查不到该主体");
        }
        /*判断用户是否拥有该主体的权限*/
        List<MainAccount> mainAccountList = serviceMerchantService.ownMainAccount(user);
        List<Long> mainAccountIdList = BeanUtils.toList(mainAccountList, "mainAccountId");
        if (!mainAccountIdList.contains(mainAccount.getMainAccountId())) {
            throw new BusException("未拥有该主体权限,下单失败");
        }

        if (serviceProductListingList==null || serviceProductListingList.size()<=0){
            throw new BusException("您已经从购物车购买过此商品，如需再次购买，请先从购物车中删除");
        }
        ServiceOrder order = new ServiceOrder();
        order.setOrderId(IdWorker.getId());
        order.setAddressId(shippingAddress.getAddressId());
        order.setPersonAddress(shippingAddress.getPersonAddress());
        order.setPhoneNo(shippingAddress.getPhoneNo());
        order.setConsignee(shippingAddress.getConsignee());
        order.setBuyerId(user.getUserId());
        order.setBuyerName(user.getUsername());
        order.setPayMainAccountId(mainAccount.getMainAccountId());
        order.setPayMainAccountName(mainAccount.getName());
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (ServiceProductListing serviceProductListing : serviceProductListingList) {
            if (serviceProductListing.getEffectiveness()!=1){
                throw new BusException(serviceProductListing.getProductName()+"的购物车已经失效下单失败");
            }
            ServiceProduct serviceProduct = serviceProductService.findById(serviceProductListing.getProductId());
            if (serviceProduct == null || serviceProduct.getStatus() == 0) {
                throw new BusException(serviceProductListing.getProductName() + "已下架,下单失败");
            }
            if (serviceProduct.getProfitMainAccountId().equals(payMainAccountId)){
                throw new BusException(serviceProduct.getProductName()+"的收益主体与所选的付款主体一样，不可购买");
            }

            if (serviceProduct.getType() == 0) {
                if (serviceProduct.getInventory() == 0) {
                    throw new BusException(serviceProduct.getProductName() + "的库存为0，购买失败");
                }
                if (serviceProductListing.getQuantity() > serviceProduct.getInventory()) {
                    throw new BusException(serviceProduct.getProductName() + "购买的数量大于库存");
                }
                ServiceProduct newServiceProduct = new ServiceProduct();
                newServiceProduct.setProductId(serviceProduct.getProductId());
                newServiceProduct.setInventory(serviceProduct.getInventory() - serviceProductListing.getQuantity());
                newServiceProduct.setUpdateTime(TimeUtils.now());
                serviceProductService.updateSelectiveById(newServiceProduct);
            }
            ServiceOrderItem serviceOrderItem = new ServiceOrderItem();
            BeanUtils.copyProperties(serviceOrderItem, serviceProduct);
            BeanUtils.copyProperties(serviceOrderItem, serviceProductListing);
            BeanUtils.copyProperties(serviceOrderItem, shippingAddress);
            if (serviceProduct.getType() == 2) {
                Date minStartDate=null;
                Date maxEndDate=null;
                if (StringUtils.isEmpty(serviceProductListing.getPersonLeaseIds())) {
                    throw new BusException(serviceProduct.getProductName() + "缺乏租赁信息，购买失败");
                }
                List<PersonLeaseMessage> personLeaseMessageList = personLeaseMessageService.findByIds(Utils.toLongIds(serviceProductListing.getPersonLeaseIds()));
                personLeaseMessageService.addOrBuyPersonLeaseMessage(0,2, user, personLeaseMessageList, serviceProduct,payMainAccountId);
                for (PersonLeaseMessage personLeaseMessage:personLeaseMessageList){
                    if (minStartDate==null){
                        minStartDate=personLeaseMessage.getStart();
                    }
                    if (maxEndDate==null){
                        maxEndDate=personLeaseMessage.getEnd();
                    }
                    if (minStartDate.getTime()>personLeaseMessage.getStart().getTime()){
                        minStartDate=personLeaseMessage.getStart();
                    }
                    if (maxEndDate.getTime()<personLeaseMessage.getEnd().getTime()){
                        maxEndDate=personLeaseMessage.getEnd();
                    }
                }
                serviceOrderItem.setMinStartDate(minStartDate);
                serviceOrderItem.setMaxEndDate(maxEndDate);

            }
            totalAmount = totalAmount.add(serviceProductListing.getTotalPrice());

            serviceOrderItem.setOrderId(order.getOrderId());

            serviceOrderItem.setGoodState(2);
            serviceOrderItem.setIsComments(0);
            serviceOrderItem.setChargingStatus(0);
            serviceOrderItem.setOrderStatus(0);
            serviceOrderItem.setCreateTime(TimeUtils.now());
            serviceOrderItem.setUpdateTime(TimeUtils.now());
            serviceOrderItem.setTotalAmount(serviceProductListing.getTotalPrice());
            serviceOrderItem.setPayableAmount(serviceProductListing.getTotalPrice());
            serviceOrderItem.setPaidAmount(BigDecimal.ZERO);
            serviceOrderItem.setPayMainAccountId(mainAccount.getMainAccountId());
            serviceOrderItem.setPayMainAccountName(mainAccount.getName());
            serviceOrderItemService.insert(serviceOrderItem);
        }
        order.setTotalAmount(totalAmount);
        order.setPayableAmount(totalAmount);
        order.setPaidAmount(BigDecimal.ZERO);
        order.setChargingStatus(0);
        order.setCreateTime(TimeUtils.now());
        order.setUpdateTime(TimeUtils.now());
        this.insert(order);
        serviceProductListingService.deleteListingByIds(listingIds,1);
        return order;
    }


    @Override
    @Transactional
    public ServiceOrder createGoodsOrderByBuyImmediately(SysUser sysUser, Long productId, Integer quantity,Long payMainAccountId,Long addressId) {
        Long listingId=serviceProductListingService.addGoodToListing(sysUser,productId,quantity,0);
        serviceProductListingService.checkLeaseListingByIds(Arrays.asList(listingId),0);
        return this.createOrder(addressId,sysUser,Arrays.asList(listingId),payMainAccountId);
    }

    @Override
    @Transactional
    public ServiceOrder createLeaseOrderByBuyImmediately(List<PersonLeaseMessage> personLeaseMessageList,SysUser sysUser, Long productId,  Long payMainAccountId, Long addressId) {
        Long listingId=serviceProductListingService.addLeaseToListing(0,sysUser, productId, personLeaseMessageList,0);
        serviceProductListingService.checkLeaseListingByIds(Arrays.asList(listingId),0);
        return this.createOrder(addressId,sysUser,Arrays.asList(listingId),payMainAccountId);
    }

    @Override
    public Page<ServiceOrder> findOrderForPage(ServiceOrderVo orderVo, int pageNo, int pageSize) {
        Example<ServiceOrder> example = ServiceOrder.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();

        CriteriaUtils.fillCondition(criteria, orderVo);

        return findPageByExample(example, pageNo, pageSize);
    }


    @Override
    public Page<ServiceProductOrderVo> findPageOrderList(ServiceOrderVo serviceOrderVo, int pageNo, int pageSize) {
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (serviceOrderVo.getTime() == null) {

        } else if (serviceOrderVo.getTime() == 0) {
            cal.add(Calendar.DATE, -7);
        } else if (serviceOrderVo.getTime() == 1) {
            cal.add(Calendar.MONTH, -1);
        } else if (serviceOrderVo.getTime() == 2) {
            cal.add(Calendar.MONTH, -3);
        } else if (serviceOrderVo.getTime() == 3) {
            cal.add(Calendar.YEAR, -1);
        }
        Example<ServiceOrder> example = ServiceOrder.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        if (serviceOrderVo.getTime() != null) {
            criteria.andBetween("createTime", cal.getTime(), date);
            serviceOrderVo.setTime(null);
        }

        CriteriaUtils.fillCondition(criteria, serviceOrderVo);
        Page<ServiceOrder> page = findPageByExample(example, pageNo, pageSize);
        List<ServiceProductOrderVo> voList = new ArrayList<>();
        for (ServiceOrder serviceOrder : page.getRecords()) {
            ServiceProductOrderVo vo = new ServiceProductOrderVo();
            vo.setServiceOrder(serviceOrder);
            vo.setItemList(orderItemService.findOrderItemListByOrderId(serviceOrder.getOrderId()));
            voList.add(vo);
        }

        Page<ServiceProductOrderVo> voPage = new Page<>(page.getCurrent(), page.getSize());
        voPage.setRecords(voList);
        voPage.setExtra(page.getExtra());
        voPage.setTotal(page.getTotal());
        return voPage;
    }

    @Override
    public Page<ServiceOrderItemVo> findPageOrderSellList(ServiceOrderItemVo serviceOrderItemVo, int pageNo, int pageSize) {

        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (serviceOrderItemVo.getTime() == null) {

        } else if (serviceOrderItemVo.getTime() == 0) {
            cal.add(Calendar.DATE, -7);
        } else if (serviceOrderItemVo.getTime() == 1) {
            cal.add(Calendar.MONTH, -1);
        } else if (serviceOrderItemVo.getTime() == 2) {
            cal.add(Calendar.MONTH, -3);
        } else if (serviceOrderItemVo.getTime() == 3) {
            cal.add(Calendar.YEAR, -1);
        }

        Example<ServiceOrderItem> example = ServiceOrderItem.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();

        if (serviceOrderItemVo.getTime() != null) {
            criteria.andBetween("createTime", cal.getTime(), date);
            serviceOrderItemVo.setTime(null);
        }

        CriteriaUtils.fillCondition(criteria, serviceOrderItemVo);
        Page<ServiceOrderItem> page = orderItemService.findPageByExample(example, pageNo, pageSize);
        List<ServiceOrderItemVo> voList = new ArrayList<>();
        for (ServiceOrderItem orderItem : page.getRecords()) {
            ServiceOrderItemVo vo = new ServiceOrderItemVo();
            BeanUtils.copyProperties(vo, orderItem);
            vo.setOrder(findById(orderItem.getOrderId()));
            voList.add(vo);
        }

        Page<ServiceOrderItemVo> sellPage = new Page<>(page.getCurrent(), page.getSize());
        sellPage.setRecords(voList);
        sellPage.setExtra(page.getExtra());
        sellPage.setTotal(page.getTotal());
        return sellPage;
    }

    @Override
    public Page<ServiceOrder> findOrderPage(Integer type, Long userId, int pageNo, int pageSize) {
        ServiceOrder order = new ServiceOrder();
        order.setBuyerId(userId);
        order.setType(type);
        Example<ServiceOrder> example = ServiceOrder.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, order);

        Page<ServiceOrder> page = findPageByExample(example, pageNo, pageSize);

        return page;
    }

    @Override
    public ServiceProductOrderVo findPageOrderDetail(Long orderId) {
        ServiceProductOrderVo vo = new ServiceProductOrderVo();
        ServiceOrder order = findById(orderId);
        List<ServiceOrderItem> orderItemList = orderItemService.findOrderItemListByOrderId(orderId);
        vo.setServiceOrder(order);
        vo.setItemList(orderItemList);
        return vo;
    }

    @Override
    public void changOrderStatus(Long orderId, Integer status) {
        ServiceOrder order = findById(orderId);
        order.setChargingStatus(status);
        updateSelectiveById(order);
    }

    @Override
    public void confirmPayOrder(Long orderId) {
        ServiceOrder order = findById(orderId);
        order.setChargingStatus(1);
       // if (order.getType() == 2) generateRoomTime(orderId);
        order.setUpdateTime(TimeUtils.now());
        updateSelectiveById(order);
        orderItemService.orderItemStatus(orderId);
    }

    @Override
    public void cancelOrder(Long orderId) {
        ServiceOrder order = findById(orderId);
        order.setChargingStatus(2);
        order.setUpdateTime(TimeUtils.now());
        updateSelectiveById(order);
    }

    @Override
    public void refundOrder(Long orderId) {
        ServiceOrder order = findById(orderId);
        order.setChargingStatus(3);
        order.setUpdateTime(TimeUtils.now());
        updateSelectiveById(order);
    }

    @Override
    public void confirmOrder(Long orderId) {
        ServiceOrder order = findById(orderId);
        order.setChargingStatus(4);
        order.setUpdateTime(TimeUtils.now());
        updateSelectiveById(order);
    }

    @Override
    public void payOrder(Long orderId, Integer payWay) {
        ServiceOrder order = new ServiceOrder();
        order.setPayWay(payWay);
        order.setOrderId(orderId);
        order.setChargingStatus(1);
        order.setUpdateTime(TimeUtils.now());
        this.updateSelectiveById(order);
    }


    @Override
    public Long countOrderNumByUserId(Long userId) {
        Example<ServiceOrder> example = ServiceOrder.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("buyerId", userId);
        ServiceOrder serviceOrder = this.findOneByExample(example);
        if (serviceOrder != null) {
            return serviceOrderItemService.countOrderNumByOrderId(serviceOrder.getOrderId());
        } else {
            return 0L;
        }

    }


    @Override
    @Transactional
    public void changeOrderStatus(Long orderId, Integer status) {
        ServiceOrder serviceOrder = this.findById(orderId);
        ServiceOrder serviceOrder1 = new ServiceOrder();
        serviceOrder1.setChargingStatus(status);
        serviceOrder1.setOrderId(serviceOrder.getOrderId());
        this.updateSelectiveById(serviceOrder1);
        serviceOrderItemService.changeStatusByServiceOrder(serviceOrder1);
    }
}